/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2012 the Initial Developer.
 * All Rights Reserved.
 *
 * The Original Code is "http://semi-frame.googlecode.com/svn/trenk/".
 *
 * The Initial Developer of the Original Code is the author below.
 */
/**
 * @file TaskConfig.cpp
 * @brief auto generated.
 * @author mornongcloud
 * @date 2012/03/11
 */

#include "semi/conf/TasksConfig.h"

namespace semi {
namespace conf {

std::string semi::conf::TasksConfig::config_file_name = "semi_task.conf";
std::string semi::conf::TasksConfig::share_file_name = "semi.TaskConfig";

TasksConfig::TasksConfig() {
	this->mTaskConf.init(share_file_name, sizeof(TasksConfig::TaskConfigs));
}

TasksConfig::~TasksConfig() {
	this->mTaskConf.end();
}

bool TasksConfig::load() {
	FILE* fp = conf::ConfigReader::open(TasksConfig::config_file_name);
	if (0 == fp) {
		//        perror("TaskConfig::load miss the semi_net.conf ");
		return false;
	}

	char cBuf[256];
	this->path = "./";

	while (fgets(cBuf, 256, fp) != 0) {

		std::string str(cBuf);

		//        str = util::StringUtil::replace(str, " ", "");
		str = util::StringUtil::replace(str, "\r", "");
		str = util::StringUtil::replace(str, "\n", "");

		int n = str.find_first_of("=", 0);
		//		if (n == std::string::npos or 0 == str.find_first_of("#", 0)) {
		if (0 == str.find_first_of("#", 0)) {
			// std::stringstream ss;
			// ss << "skip line " << lno;
			// ss << " \"" << str << "\"";
			// std::cout << ss.str() << std::endl;
			continue;
		}

		// read line
		std::string key = str.substr(0, n);
		std::string val;
		if (n != std::string::npos)
			val = str.substr(n + 1, str.length());

		//		std::cout << key << "=" << val << std::endl;

		// left value
		int idx = 0;
		std::string keys[8] = { "", "", "", "", "", "", "", "" };
		for (int i = 0, n; i <= key.length(); i = n + 1) {
			n = key.find_first_of(".", i);
			if (n == std::string::npos)
				n = str.length();
			keys[idx] = key.substr(i, n - i);
			// std::cout << "key : " << keys[idx] << std::endl;
			idx++;
		}
		if ("" == keys[0])
			continue; // next line;

		// task
		else if (keys[0] == "task") {
			if ("" == keys[1])
				continue; // next line;
			else if ("path" == keys[1])
				this->path = val; // default execute directory
			else if (0 < keys[1].length()) {
				// std::cout << keys[1] << " : " << val << std::endl;
				if (0 == m_task_path.count(keys[1]))
					m_task_path[keys[1]] = this->path + keys[1]; // execute path
			} else if ("" == keys[2])
				continue; // next line;
			// argument
			if (keys[2] == "args")
				m_task_args[keys[1]] = val;
			// timer
			else if (keys[2] == "date" || keys[2] == "time" || keys[2]
					== "cycl") {
				// timer date
				if (keys[2] == "date")
					m_timer_d[keys[1]] = val;
				// timer time stamp
				else if (keys[2] == "time")
					m_timer_t[keys[1]] = val;
				// timer cycle
				else if (keys[2] == "cycl")
					m_timer_c[keys[1]] = val;
			}
		}
	}

	fclose(fp); // configure file is one
	// loaded = true;
	return true;
	return true;
}

bool TasksConfig::setSharedMemory() {

	// read file
	bool bl = this->load();

	if (!bl)
		return false;

	TasksConfig::TaskConfigs* tconfs =
			(TasksConfig::TaskConfigs*) this->mTaskConf.get();

	memset(tconfs, 0, sizeof(TasksConfig::TaskConfigs));

	// set all tasks on memory
	for (util::StringMap::iterator iter = this->m_task_path.begin(); iter
			!= this->m_task_path.end(); iter++) { // every execute path

		std::string tskid = util::StringUtil::trim((std::string) iter->first); // task id

		int idxt = 0;
		for (; idxt < (sizeof(TaskConfigs) / sizeof(TaskConfig)); idxt++) {
			if (tconfs->taskConfig[idxt].task_id == 0)
				break;
			std::string tmp(tconfs->taskConfig[idxt].task_id);
			if (tmp.length() == 0 || tmp == tskid)
				break;
			if ((sizeof(TaskConfigs) / sizeof(TaskConfig)) == idxt - 1)
				//TODO throw logic error?;
				return false;
		}

		// task id
		memset(tconfs->taskConfig[idxt].task_id, 0,
				sizeof(tconfs->taskConfig[idxt].task_id));
		strncpy(tconfs->taskConfig[idxt].task_id, tskid.c_str(), tskid.length());
		// path
		memset(tconfs->taskConfig[idxt].task_path, 0,
				sizeof(tconfs->taskConfig[idxt].task_path));
		std::string pth = util::StringUtil::trim((std::string) iter->second); // path
		strncpy(tconfs->taskConfig[idxt].task_path, pth.c_str(), pth.length());
		// args
		memset(tconfs->taskConfig[idxt].task_args, 0,
				sizeof(tconfs->taskConfig[idxt].task_args));
		std::string arg = " ";
		if (0 < this->m_task_args.count(tskid))
			//            arg = util::StringUtil::trim(this->m_task_args[tskid]); // arg
			arg = this->m_task_args[tskid]; // arg
		strncpy(tconfs->taskConfig[idxt].task_args, arg.c_str(), arg.length());

		// timer
		tconfs->taskConfig[idxt].timer_t[0] = timer_any_value;
		tconfs->taskConfig[idxt].timer_t[1] = timer_any_value;
		tconfs->taskConfig[idxt].timer_t[2] = timer_any_value;
		tconfs->taskConfig[idxt].timer_d[0] = timer_any_value;
		tconfs->taskConfig[idxt].timer_d[1] = timer_any_value;
		tconfs->taskConfig[idxt].timer_d[2] = timer_any_value;

		if (0 < this->m_timer_d.count(tskid) || 0
				< this->m_timer_t.count(tskid) || 0 < this->m_timer_c.count(
				tskid)) {
			tconfs->taskConfig[idxt].timer = 1;

			std::string date = this->m_timer_d[tskid];
			std::string time = this->m_timer_t[tskid];
			std::string cycl = this->m_timer_c[tskid];

			if (0 < cycl.length())
				tconfs->taskConfig[idxt].timer_c = atoi(cycl.c_str());

			//            std::cout << tskid << " taskConfig[" << idxt << "]" << date << " "
			//                    << time << " " << cycl << std::endl;

			semi::util::Strings ts = semi::util::StringUtil::split(time, ":");
			if (2 < ts.size()) {
				util::Strings::iterator iter = ts.begin();
				if (iter != ts.end()) {
					std::string str = *iter;
					if ("*" == str)
						tconfs->taskConfig[idxt].timer_t[0] = -1;
					else if (0 < str.length())
						tconfs->taskConfig[idxt].timer_t[0] = (short) atoi(
								str.c_str());
					iter++;
				}
				if (iter != ts.end()) {
					std::string str = *iter;
					if ("*" == str)
						tconfs->taskConfig[idxt].timer_t[1] = -1;
					else if (0 < str.length())
						tconfs->taskConfig[idxt].timer_t[1] = (short) atoi(
								str.c_str());
					iter++;
				}
				if (iter != ts.end()) {
					std::string str = *iter;
					if ("*" == str)
						tconfs->taskConfig[idxt].timer_t[2] = -1;
					else if (0 < str.length())
						tconfs->taskConfig[idxt].timer_t[2] = (short) atoi(
								str.c_str());
					iter++;
				}

				semi::util::Strings ds = semi::util::StringUtil::split(date,
						"/");
				if (2 < ds.size()) {
					util::Strings::iterator iter = ds.begin();
					if (iter != ds.end()) {
						std::string str = *iter;
						if ("*" == str)
							tconfs->taskConfig[idxt].timer_d[0] = -1;
						else if (0 < str.length())
							tconfs->taskConfig[idxt].timer_d[0] = (short) atoi(
									str.c_str());
						iter++;
					}
					if (iter != ds.end()) {
						std::string str = *iter;
						if ("*" == str)
							tconfs->taskConfig[idxt].timer_d[1] = -1;
						else if (0 < str.length())
							tconfs->taskConfig[idxt].timer_d[1] = (short) atoi(
									str.c_str());
						iter++;
					}
					if (iter != ds.end()) {
						std::string str = *iter;
						if ("*" == str)
							tconfs->taskConfig[idxt].timer_d[2] = -1;
						else if (0 < str.length())
							tconfs->taskConfig[idxt].timer_d[2] = (short) atoi(
									str.c_str());
						iter++;
					}

				}

			}

		}
	}
	this->mTaskConf.end();

	return true;
}

TasksConfig::TaskConfig TasksConfig::getConfig(std::string tskid) {

	if (Configurator::needReload()) { // change?
		this->setSharedMemory();
		conf::Configurator().setSharedMemory();
	}

	TaskConfigs *tconfs = (TaskConfigs*) this->mTaskConf.get(PROT_READ);

	for (int idx = 0; idx < (sizeof(TasksConfig::TaskConfigs)
			/ sizeof(TasksConfig::TaskConfig)); idx++) {
		TasksConfig::TaskConfig cnf = tconfs->taskConfig[idx];

		std::string tmp(cnf.task_id);
		if (0 != cnf.task_id && tmp == tskid) {
			TaskConfig ret;
			memcpy(&ret, &cnf, sizeof(TaskConfig));
			this->mTaskConf.end();
			tconfs = 0;
			return ret;
		}
	}
	this->mTaskConf.end();
	tconfs = 0;

	TaskConfig ret;
	memset(&ret, 0, sizeof(TaskConfig));
	memset(&ret.timer_t, -1, sizeof(ret.timer_t));
	//    ret.timer_c = -1;
	return ret;
}

// static
TasksConfig::TaskConfigs TasksConfig::getConfigs() {

	semi::posix::SharedMemory mTask(share_file_name,
			sizeof(TasksConfig::TaskConfigs));
	TaskConfigs *tconfs = (TaskConfigs*) mTask.get(PROT_READ);
	TaskConfigs ret;
	memcpy(&ret, tconfs, sizeof(TaskConfigs));
	mTask.end();
	tconfs = 0;
	return ret;
}

// static
std::string TasksConfig::toString() {

	std::stringstream ss;
	ss << std::endl << share_file_name << " (" << TasksConfig::config_file_name
			<< ")" << std::endl;
	semi::posix::SharedMemory mTask(share_file_name,
			sizeof(TasksConfig::TaskConfigs));
	TaskConfigs *tconfs = (TaskConfigs*) mTask.get(PROT_READ);
	int cnt = 0;
	for (int idx = 0; idx < (sizeof(TasksConfig::TaskConfigs)
			/ sizeof(TasksConfig::TaskConfig)); idx++) {
		TasksConfig::TaskConfig cnf = tconfs->taskConfig[idx];
		if (0 != cnf.task_id && 0 != cnf.task_id[0]) {
			ss << "    ";
			if (idx < 10)
				ss << '0';
			ss << idx << " id:" << cnf.task_id << " psth:" << cnf.task_path
			//                    << " args:" << cnf.task_args
					<< " timer:" << cnf.timer;
			if (0 < cnf.timer) {
				ss << "    ";
				if (0 <= cnf.timer_d[0] && cnf.timer_d[0] < 10)
					ss << "0";
				ss << cnf.timer_d[0] << "/";
				if (0 <= cnf.timer_d[1] && cnf.timer_d[1] < 10)
					ss << "0";
				ss << cnf.timer_d[1] << "/";
				if (0 <= cnf.timer_d[2] && cnf.timer_d[2] < 10)
					ss << "0";
				ss << cnf.timer_d[2] << "  ";

				if (0 <= cnf.timer_t[0] && cnf.timer_t[0] < 10)
					ss << "0";
				ss << cnf.timer_t[0] << ":";
				if (0 <= cnf.timer_t[1] && cnf.timer_t[1] < 10)
					ss << "0";
				ss << cnf.timer_t[1] << ":";
				if (0 <= cnf.timer_t[2] && cnf.timer_t[2] < 10)
					ss << "0";
				ss << cnf.timer_t[2] << " cycle:" << cnf.timer_c;
			}
			ss << std::endl;
			cnt++;
		}
	}
	mTask.end();
	ss << "    display count:" << cnt << std::endl;
	return ss.str();
}

}
}
